package cn.tedu.web.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.tedu.web.entity.Wallet;
import cn.tedu.web.entity.WalletAccount;
import cn.tedu.web.mapper.OrderMapper;
import cn.tedu.web.mapper.WalletMapper;
import cn.tedu.web.service.IWalletService;

/**
 * <p>
 * 【我的钱包】 服务实现类
 * </p>
 *
 * @author issen
 * @since 2021-10-23
 */
@Service
public class WalletServiceImpl extends ServiceImpl<WalletMapper, Wallet> implements IWalletService {
    @Resource
    private WalletMapper walletMapper;
    @Resource
    private OrderMapper orderMapper;

    public BigDecimal findAmountById(Integer id) {
        return walletMapper.findAmountById(id);
    }

    public boolean exists(Integer id) {
        return walletMapper.exists(id);
    }

    /**
     * 初始化支付密码
     *
     * @param id       用户的ID
     * @param password 初始的密码
     * @return
     */
    public Integer initPaymentPassword(Integer id, String password) {
        if (id == null || id < 1 || StringUtils.isEmpty(password)) {
            return -1;
        }
        if (exists(id)) {
            return 0;
        }
        return walletMapper.init(id, password);
    }

    /**
     * 充值
     */
    @Transactional
    public Integer recharge(Integer id, String password, Double amount) {
        if (id == null || id < 1 || amount == null || StringUtils.isEmpty(password)) {
            return -1;
        }
        // 校验支付密码是否正确，校验订单编号是否存在，订单状态是否被允许支付
        if (!walletMapper.checkPassword(id, password)) {
            // 校验支付密码是否正确
            return -2;
        }
        amount = Math.abs(amount);
        // 充值
        Integer affectRows = walletMapper.updateAmount(id, password, amount);
        // 记录充值的流水
        WalletAccount account = new WalletAccount();
        account.setAmount(BigDecimal.valueOf(amount));
        account.setDescription("平台支付充值，面额：￥" + amount + "元");
        account.setUid(id);
        account.setType(1);
        affectRows += walletMapper.insertWalletAccount(account);
        return affectRows;
    }

    /**
     * 查询指定账户的交易流水
     */
    public List<WalletAccount> findAll(Integer id) {
        if (id == null || id < 1) {
            return new ArrayList<>();
        }
        return walletMapper.findAll(id);
    }

    /**
     * 某用户支付订单的功能
     *
     * @param userid   用户的ID
     * @param password 用户的支付密码
     * @param orderid  订单的编号
     */
    @Transactional
    public Integer pay(Integer userid, String password, String orderid) {
        if (userid == null || userid < 1 || StringUtils.isAnyBlank(password, orderid)) {
            return -1;
        }
        // 支付的步骤：
        // 0. 校验支付密码是否正确，校验订单编号是否存在，订单状态是否被允许支付
        if (!walletMapper.checkPassword(userid, password)) {
            // 校验支付密码是否正确
            return -2;
        }
        // 获取实付金额, 如果该值为 null, 或者小于零, 则说明订单不存在
        Double amount = orderMapper.findAmountById(orderid, userid);
        if (amount == null || amount < 0) {
            // 订单不存在， 返回 -3
            return -3;
        }
        if (!orderMapper.isUnpaid(orderid)) {
            // 当订单的状态不是【待支付】的时候，不允许执行扣款流程
            return -4;
        }
        if (!walletMapper.isSufficient(userid, amount)) {
            // 当前余额不足以支付相应的金额，不允许执行扣款流程
            return -5;
        }
        // 1. 扣款
        Integer affectRows = walletMapper.updateAmount(userid, password, 0 - amount);
        // 2. 记录流水
        WalletAccount account = new WalletAccount();
        account.setAmount(BigDecimal.valueOf(0 - amount));
        account.setDescription("平台支付的消费，订单编号：" + orderid);
        account.setUid(userid);
        account.setType(0);
        affectRows += walletMapper.insertWalletAccount(account);
        // 3. 修改订单状态， 已支付,待发货【支付成功之后的状态】
        affectRows += orderMapper.updateStatus(orderid, 2);
        return affectRows;
    }
}
